home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacWorld 1998 January
/
Macworld (1998-01).dmg
/
Shareware World
/
Comms & Internet
/
HTML mode 2.0 etc.
/
htmlHomePageUtils.tcl
< prev
next >
Wrap
Text File
|
1997-09-22
|
54KB
|
1,480 lines
## -*-Tcl-*-
# ###################################################################
# HTML mode - tools for editing HTML documents
#
# FILE: "htmlHomePageUtils.tcl"
# created: 97-06-26 12.51.42
# last update: 97-09-22 16.39.16
# Author: Johan Linde
# E-mail: <jl@theophys.kth.se>
# www: <http://bach.theophys.kth.se/~jl/Alpha.html>
#
# Version: 2.0
#
# Copyright 1996, 1997 by Johan Linde
#
# This software may be used freely, and distributed freely, as long as the
# receiver is not obligated in any way by receiving it.
#
# If you make improvements to this file, please share them!
#
# ###################################################################
##
#===============================================================================
# Checking links
#===============================================================================
# Check that links are valid.
proc htmlCheckWindow {} {htmlCheckLinks Window}
proc htmlCheckHomePage {} {htmlCheckLinks Home}
proc htmlCheckFolder {} {htmlCheckLinks Folder}
proc htmlCheckFile {} {htmlCheckLinks File}
proc htmlCheckLinks {where {checking 1}} {
global HTMLmodeVars
# Save all open window?
if {$where != "Window" &&
[htmlAllSaved "-c {Save all open windows before checking links?}"] == "cancel"} { return}
set filebase 0
if {$where == "File"} {
if {[catch {getfile "Select file to scan."} files]} {return}
# Is this a text file?
if {![htmlIsTextFile $files alertnote]} {return}
set base [htmlBASEfromPath $files]
if {$HTMLmodeVars(useBigBrother)} {htmlBigBrother "$files"; return}
set path [lindex $base 1]
set homepage [lindex $base 3]
set isinfld [lindex $base [expr 3 + [lindex $base 4] / 2]]
set base [lindex $base 0]
if {$base == "file:///"} {set filebase [string length "[file dirname $files]:"]}
set filelist [htmlOpenAfile]
puts [lindex $filelist 0] $files
close [lindex $filelist 0]
set files [lindex $filelist 1]
} elseif {$where == "Window"} {
set files [stripNameCount [lindex [winNames -f] 0]]
if {![file exists $files]} {
if {[lindex [dialog -w 200 -h 70 -t "You must save the window." 10 10 390 30 \
-b Save 20 40 85 60 \
-b Cancel 110 40 175 60] 1]} {
error ""
}
if {![catch {saveAs "Untitled.html"}]} {
set files [stripNameCount [lindex [winNames -f] 0]]
} else {
error ""
}
} else {
if {[winDirty] && [askyesno "Save window?"] == "yes"} {save}
}
set base [htmlBASEfromPath $files]
if {$checking != 2 && $HTMLmodeVars(useBigBrother)} {htmlBigBrother "$files"; return}
set path [lindex $base 1]
set homepage [lindex $base 3]
set isinfld [lindex $base [expr 3 + [lindex $base 4] / 2]]
set base [lindex $base 0]
if {$base == "file:///"} {set filebase [string length "[file dirname $files]:"]}
set filelist [htmlOpenAfile]
puts [lindex $filelist 0] $files
close [lindex $filelist 0]
set files [lindex $filelist 1]
} elseif {$where == "Folder"} {
if {[catch {htmlGetDir "Folder to scan."} folder]} {return}
set base [htmlBASEfromPath $folder]
set subFolders [expr ![string compare yes [askyesno "Check files in subfolders?"]]]
if {$subFolders && ![set subFolders [expr ![htmlContainHpFolder $folder]]] &&
[lindex [dialog -w 410 -h 135 -t "The folder '[file tail $folder]' contains a\
home page folder or an include folder, but is itself not inside one. You can't\
simultaneously check links both inside and outside home page or include folders.\
Sorry!\rBut\
you can still check this folder and skip the subfolders." 10 10 400 90\
-b Check 20 105 85 125 -b Cancel 110 105 175 125] 1]} {return}
if {$HTMLmodeVars(useBigBrother)} {htmlBigBrother "$folder:" $subFolders; return}
set path [lindex $base 1]
set homepage [lindex $base 3]
set isinfld [lindex $base [expr 3 + [lindex $base 4] / 2]]
set base [lindex $base 0]
if {$base == "file:///"} {set filebase [string length "$folder:"]}
if {$subFolders} {
set files [htmlAllHTMLfiles $folder 1]
} else {
set files [htmlGetHTMLfiles $folder 1]
}
} else {
# Check that a home page is defined.
if {![htmlIsThereAHomePage]} {return}
if {[catch {htmlWhichHomePage "check links in"} hp]} {return}
set homepage [lindex $hp 0]
set isinfld $homepage
if {$HTMLmodeVars(useBigBrother)} {htmlBigBrother "$homepage:" 1; return}
set files [htmlAllHTMLfiles $homepage 1]
set base [lindex $hp 1]
set path [lindex $hp 2]
}
return [htmlScanFiles $files $base $path $homepage $isinfld $checking $filebase]
}
# Select a new file for an invalid link.
proc htmlLinkToNewFile {} {
if {![string match "*Invalid URLs*" [set win [lindex [winNames] 0]]] || [lindex [posToRowCol [getPos]] 0] < 3} {return}
set str [getText [lineStart [getPos]] [expr [nextLineStart [getPos]] - 1]]
gotoMatch
regexp {Line [0-9]+:([^∞]+)} $str dum url
regsub -all {\((BASE|Invalid|anchor|case)[^\)]+\)} $url "" url
set url [string trim $url]
set str ""
regexp {[^#]*} $url str
set anchor [string trim [string range $url [string length $str] end] \"]
regsub -all {[\(\)]} $url {\\\0} url
if {[catch {search -s -f 1 -i 0 -r 1 -m 0 -l [selEnd] $url [getPos]} res]} {
alertnote "Can't find link to change on selected line."
return
}
if {[set newFile [htmlGetFile]] == ""} {return}
set newLink [lindex $newFile 0]
set wh [lindex $newFile 1]
if {$wh == "" && $anchor != "" && [htmlCheckAnchor $pathToNewFile $url]} {
append newLink $anchor
}
set f [htmlURLescape2 $newLink]
if {![regsub {([^=]+=)(\"[^\"]+\"|[^ ]+)} $url "\\1\"$f\"" url]} {set url url(\"$f\")}
replaceText [set start [lindex $res 0]] [lindex $res 1] $url
# If it's an IMG tag, replace WIDTH and HEIGHT.
if {$wh != "" && [string toupper [string range $url 0 2]] == "SRC" &&
![catch {search -s -f 0 -i 1 -r 1 -m 0 {<IMG[ \t\r\n]+[^<>]+>} $start} res1] &&
[lindex $res1 1] > [lindex $res 1]} {
if {![catch {search -s -f 1 -i 1 -r 1 -m 0 -l [expr [lindex $res1 1] + 1] {WIDTH=\"?[0-9]*\"?} [lindex $res1 0]} res2]} {
replaceText [lindex $res2 0] [lindex $res2 1] [htmlSetCase WIDTH=\"[lindex $wh 0]\"]
}
if {![catch {search -s -f 1 -i 1 -r 1 -m 0 -l [expr [lindex $res1 1] + 1] {HEIGHT=\"?[0-9]*\"?} [lindex $res1 0]} res2]} {
replaceText [lindex $res2 0] [lindex $res2 1] [htmlSetCase HEIGHT=\"[lindex $wh 1]\"]
}
}
# Remove line with corrected link.
bringToFront $win
setWinInfo read-only 0
deleteText [lineStart [getPos]] [nextLineStart [getPos]]
select [lineStart [getPos]] [nextLineStart [getPos]]
setWinInfo dirty 0
setWinInfo read-only 1
}
bind '\r' <o> htmlLinkToNewFile Brws
bind enter <o> htmlLinkToNewFile Brws
proc htmlBbthReadSettings {} {
set allSettings [AEBuild -r 'Bbth' core getd ---- "obj{want:type('reco'),from:null(),form:'prop',seld:type('allS')}"]
set allSettings [string range $allSettings 17 [expr [string length $allSettings] - 2]]
return $allSettings
}
proc htmlBbthRestoreSettings {settings} {
AEBuild 'Bbth' core setd "----" "obj{want:type('reco'),from:null(),form:'prop',seld:type('allS')}" "data" $settings
}
proc htmlBigBrother {path {searchSubFolder 0}} {
global HTMLmodeVars
# define url mapping
set urlmap [htmlURLmap]
# launches Big Brother
if {![htmlCheckRunning Bbth] && [catch {launchBackAppl Bbth}]} {
alertnote "Could not find or launch Big Brother."
return
}
if {[set vers [htmlGetVersion Bbth]] >= 1.1} {
# Read all settings.
set allSettings [htmlBbthReadSettings]
# Change settings
if {!$HTMLmodeVars(useBBoptions)} {
AEBuild 'Bbth' core setd "----" "obj{want:type('bool'),from:null(),form:'prop',seld:type('Loly')}" "data" "bool(«0$HTMLmodeVars(ignoreRemote)»)"
AEBuild 'Bbth' core setd "----" "obj{want:type('bool'),from:null(),form:'prop',seld:type('Roly')}" "data" "bool(«0$HTMLmodeVars(ignoreLocal)»)"
}
AEBuild 'Bbth' core setd "----" "obj{want:type('bool'),from:null(),form:'prop',seld:type('Sfld')}" "data" "bool(«0$searchSubFolder»)"
AEBuild 'Bbth' core setd "----" "obj{want:type('mapG'),from:null(),form:'prop',seld:type('mapS')}" "data" "\[$urlmap\]"
} else {
alertnote "Cannot change the settings in Big Brother. You need Big Brother 1.1 or later."
}
# Sends a file or folder to be opened.
sendOpenEvent noReply 'Bbth' $path
# Restore settings
if {$vers >= 1.1} {htmlBbthRestoreSettings $allSettings}
if {$HTMLmodeVars(checkInFront)} {switchTo 'Bbth'}
}
# Checking of remote links in a document
proc htmlCheckRemoteLinks {} {
global htmlNumBbthChecking
if {[htmlGetVersion Bbth] < 1.2} {
alertnote "You need Big Brother 1.2 or later to check and fix remote links."
return
}
set urlList [htmlCheckLinks Window 2]
if {![llength $urlList]} {alertnote "No remote links to check."; return}
if {![htmlCheckRunning Bbth] && [catch {launchBackAppl Bbth}]} {
alertnote "Could not find or launch Big Brother."
return
}
set htmlBbthChkdWin [stripNameCount [lindex [winNames -f] 0]]
set sep ""
foreach url $urlList {
append theRecord "$sep{Url :“[lindex $url 1]”, Id# :“[concat $url $htmlBbthChkdWin]”}"
set sep ", "
}
# Read all settings.
set allSettings [htmlBbthReadSettings]
# Don't ignore remote links
AEBuild 'Bbth' core setd "----" "obj{want:type('bool'),from:null(),form:'prop',seld:type('Loly')}" "data" "bool(«00»)"
# No url mappings.
AEBuild 'Bbth' core setd "----" "obj{want:type('mapG'),from:null(),form:'prop',seld:type('mapS')}" "data" "\[\]"
AEBuild 'Bbth' "Bbth" "Chck" "----" "\[$theRecord\]"
htmlBbthRestoreSettings $allSettings
incr htmlNumBbthChecking [llength $urlList]
}
# Takes care of events sent from Big Brother.
proc htmlBbthChkdHandler {arg} {
global tileLeft tileTop tileWidth errorHeight htmlNumBbthChecking
regexp {'Id# ':“([^”]+)”} $arg dum id
regexp {CRes:([^,]+)} $arg dum result
set win [lrange $id 2 end]
switch $result {
RSuc {set str "The remote document exists."; set color 3}
LSuc {set str "The local document exists."; set color 3}
SFld {
set color 5
regexp {SCod:([^,]+)} $arg dum code
switch $code {
"204" {set str "The document exists but contains no data."}
"400" {set str "The server (or the proxy) reports a bad request."}
"401" {set str "The document seems to exist but a password is required to access it."}
"403" {set str "The document still exists but the server refuses to deliver it."}
"404" {set str "The remote document doesn't exist."}
"500" {set str "The server reports an internal error while trying to serve our request."}
"501" {set str "The server doesn't seem to support checking the existence of a link."}
"502" {set str "A gateway reported an error."}
"503" {set str "The server is currently unable to deliver this document. This situation might be temporary."}
default {set str "The server answered with an unknown HTTP response code."}
}
}
SMvd {
set color 1
regexp {SCod:([^,]+)} $arg dum code
regexp {nURL:“([^”]+)”} $arg dum newURL
switch $code {
"301" {set str "The document has moved permanently to $newURL."}
"302" {set str "The document has moved temporarily to $newURL."}
default {set str "The document has moved to $newURL."}
}
edit -c -w $win
set l [rowColToPos [lindex $id 0] 0]
if {![catch {search -s -f 1 -i 1 -m 0 -r 0 -l [nextLineStart $l] [lindex $id 1] [lineStart $l]} res]} {
eval replaceText $res $newURL
}
}
sFld {
set color 5
regexp {sRsn:([^,]+)} $arg dum reason
switch $reason {
bnAb {set str "Invalid base URL: it should be an absolute URL."}
nTCP {set str "MacTCP or Open Transport TCP/IP is needed to check remote links."}
locF {set str "Invalid local link."}
Open {set str "Initializing the network services failed."}
Bind {set str "Selecting a local port failed."}
Rslv {set str "Resolving the host name failed."}
Conn {set str "Establishing the connection failed."}
Send {set str "Sending the request failed."}
Recv {set str "Receiving the server's answer failed."}
Disc {set str "Closing the connection failed."}
Pars {set str "The server's response doesn't conform to the HTTP/1.0 protocol."}
Empt {set str "The server closed the connection without answering."}
IncT {set str "The server sent only part of the document."}
SWDr {set str "The server said the document exists, but wasn't able to deliver it."}
NTr/ {set str "This URL should end with a slash because it points to a directory."}
default {set str "Checking the link failed for an unknown reason."}
}
}
Sntx {set str "URL syntax error."; set color 5}
}
if {[lsearch -exact [winNames -f] "* Remote URLs *"] < 0} {
new -n "* Remote URLs *" -g $tileLeft $tileTop $tileWidth $errorHeight
insertText "Link checking results: (<uparrow> and <downarrow> to browse, <return> to go to line\rLinks to moved pages have been changed.\r"
htmlSetWin Brws
}
bringToFront "* Remote URLs *"
setWinInfo read-only 0
goto [maxPos]
insertText "Line [lindex $id 0]: "
insertColorEscape [getPos] $color
insertText "$str"
insertColorEscape [getPos] 0
insertText " [lindex $id 1]\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t∞$win\r"
incr htmlNumBbthChecking -1
if {!$htmlNumBbthChecking} {insertText "Done.\r"}
htmlRedraw
setWinInfo dirty 0
setWinInfo read-only 1
}
# Returns a list of all HTML and CSS files in a folder and its subfolders.
proc htmlAllHTMLfiles {folder {CSS 0} {toExclude ""}} {
message "Building file list…"
set filelist [htmlOpenAfile]
set fid [lindex $filelist 0]
set files [lindex $filelist 1]
set folders [list $folder]
while {[llength $folders]} {
set newFolders ""
foreach fl $folders {
htmlGetHTMLfiles $fl $CSS $fid $toExclude
# Get folders in this folder.
if {![catch {glob "$fl:*:"} filelist]} {
foreach fil $filelist {
lappend newFolders [string trimright $fil :]
}
}
}
set folders $newFolders
}
close $fid
return $files
}
# Finds all HTML files in a folder
proc htmlGetHTMLfiles {folder {CSS 0} {fid ""} {toExclude ""}} {
global filepats
set pats $filepats(HTML)
if {$CSS && [info exists filepats(CSS)]} {append pats " " $filepats(CSS)}
set files ""
set cl 0
if {$fid == ""} {
set filelist [htmlOpenAfile]
set fid [lindex $filelist 0]
set files [lindex $filelist 1]
set cl 1
}
if {![catch {glob -t TEXT $folder:*} filelist]} {
foreach fil $filelist {
foreach suffix $pats {
if {[string match $suffix $fil] && [lsearch -exact $toExclude $fil] < 0} {
puts $fid $fil
break
}
}
}
}
if {$cl} {close $fid}
return $files
}
# Opens a filelist file. Returns fileid and path.
proc htmlOpenAfile {} {
global PREFS
if {![file exists $PREFS:HTMLtmp]} {mkdir $PREFS:HTMLtmp}
set i 0
while {[file exists $PREFS:HTMLtmp:tempfile$i]} {incr i}
set fid [open $PREFS:HTMLtmp:tempfile$i w+]
return [list $fid "$PREFS:HTMLtmp:tempfile$i"]
}
# checking = 1 or 2: called from htmlCheckLinks
# checking = 1:
# Scan a list of files for HTML links and check if they point to existing files.
# checking = 2:
# Scan a list of files for HTML links and return the remote ones for checking with Big Brother.
# checking = 0: called from htmlMoveFiles
# Build a list of links which point to the files just moved.
proc htmlScanFiles {files baseURL basePath homepage isInFolder checking filebase {movedFiles ""}} {
global htmlURLAttr winModes HTMLmodeVars
global tileLeft tileTop tileWidth errorHeight
global htmlCaseFolders htmlCaseFiles
set htmlCaseFolders ""; set htmlCaseFiles ""
set chCase $HTMLmodeVars(caseSensitive)
set chAnchor $HTMLmodeVars(checkAnchors)
# Build regular expressions with URL attrs.
set exp "<!--|\[ \\t\\n\\r\]+("
foreach attr $htmlURLAttr {
append exp "$attr|"
}
set exp [string trimright $exp |]
append exp ")"
set expBase "<base\[ \\t\\n\\r\]+\[^>\]*>"
set expBase2 "(href=)\"?(\[^ \\t\\n\\r\">\]+)\"?"
set exp1 "${exp}(\"\[^\">\]+\"|\[^ \\t\\n\\r>\]+)"
set exp2 {/\*|[ \t\r\n]+(url)\(\"?([^\"\)]+)\"?\)}
set toCheck ""
if {$checking != 2} {
set result [htmlOpenAfile]
set fidr [lindex $result 0]
}
set checkFail 0
set commStart1 "<!--"
set commEnd1 "-->"
set commStart2 {/*}
set commEnd2 {\*/}
# Open file with filelist
set fid0 [open $files]
while {![eof $fid0]} {
gets $fid0 f
if {$f == "" || [catch {open $f} fid]} {continue}
set base $baseURL
set path $basePath
set hpPath $homepage
if {$isInFolder == ""} {
set epath $f
} else {
set epath [string range $f [expr [string length $isInFolder] + 1] end]
}
regsub -all {:} $epath {/} epath
set baseText ""
message "Looking at [file tail $f]…"
set filecont [read $fid 16384]
set limit [expr [eof $fid] ? 0 : 300]
if {[regexp {\n} $filecont]} {
set newln "\n"
} else {
set newln "\r"
}
# Look for BASE.
if {[regexp -nocase -indices $expBase $filecont thisLine]} {
set preBase [string range $filecont 0 [lindex $thisLine 0]]
set comm 0
while {[regexp -indices {<!--} $preBase bCom]} {
set preBase [string range $preBase [expr [lindex $bCom 1] - 1] end]
set comm 1
if {[regexp -indices -- {-->} $preBase bCom]} {
set preBase [string range $preBase [expr [lindex $bCom 1] - 1] end]
set comm 0
} else {
break
}
}
if {!$comm && [regexp -nocase $expBase2 [string range $filecont [lindex $thisLine 0] [lindex $thisLine 1]] href b url]} {
if {![catch {htmlBASEpieces $url} basestr]} {
set base [lindex $basestr 0]
set path [lindex $basestr 1]
set epath [lindex $basestr 2]
set hpPath ""
set baseText "(BASE used) "
} else {
set baseText "(Invalid BASE) "
}
}
}
for {set i1 1} {$i1 < 3} {incr i1} {
set exprr [set exp$i1]
if {$i1 == 2} {
seek $fid 0
set filecont [read $fid 16384]
set limit [expr [eof $fid] ? 0 : 300]
}
set commStart [set commStart$i1]
set commEnd [set commEnd$i1]
set linenum 1
set comment 0
while {1} {
# Find all links in every line.
while {$comment || ([regexp -nocase -indices $exprr $filecont href b url] &&
[expr [string length $filecont] - [lindex $href 0]] > $limit)} {
# Comment?
if {$comment || [string range $filecont [lindex $href 0] [lindex $href 1]] == $commStart} {
if {$comment} {
set href {0 0}
set subcont $filecont
} else {
set subcont [string range $filecont [expr [lindex $href 1] + 1] end]
}
if {[regexp -indices -- $commEnd $subcont cend] &&
[expr [string length $subcont] - [lindex $cend 0]] > $limit} {
incr linenum [regsub -all $newln [string range $filecont 0 [expr [lindex $href 1] + [lindex $cend 1]]] {} dummy]
set filecont [string range $filecont [expr [lindex $href 1] + [lindex $cend 1]] end]
set comment 0
continue
} else {
set comment 1
break
}
}
incr linenum [regsub -all $newln [string range $filecont 0 [lindex $url 0]] {} dummy]
set linkTo [htmlURLunEscape [string trim [string range $filecont [lindex $url 0] [lindex $url 1]] \"]]
set nogood 0
if {[catch {htmlPathToFile $base $path $epath $hpPath $linkTo} linkToPath]} {
if {$linkToPath == ""} {
set nogood 1
} elseif {$checking == 2 && [string range $linkToPath 0 6] == "http://"} {
# Checking remote links
lappend toCheck [list $linenum $linkToPath]
}
set linkToPath ""
} else {
# Anchors always point to the file itself, unless there's a BASE.
if {[string index $linkTo 0] == "#" && $baseText == ""} {set linkToPath [list $f $f]}
set casePath [lindex $linkToPath 1]
set linkToPath [lindex $linkToPath 0]
}
# If this is BASE HREF, ignore it.
if {[string length $baseText] && [regexp -nocase -indices $expBase $filecont thisLine] \
&& [regexp -nocase $expBase2 [string range $filecont [lindex $thisLine 0] [lindex $thisLine 1]]]\
&& [lindex $thisLine 0] < [lindex $url 0] && [lindex $thisLine 1] > [lindex $url 1]} {
set linkToPath ""
}
if {$checking == 1} {
set anchorCheck 1
set caseOK 1
set fext [file exists $linkToPath]
if {$chAnchor && $linkToPath != "" && [regexp {#} $linkTo] && $fext} {set anchorCheck [htmlCheckAnchor $linkToPath $linkTo]}
if {$chCase && $linkToPath != "" && $fext} {set caseOK [htmlCheckLinkCase $linkToPath $casePath]}
# Does the file exist? Ignore it if it's outside home page folder.
# Then it point to someone else's home page.
if {!$anchorCheck || $nogood || !$caseOK || ( $linkToPath != "" && !$fext)} {
set bText $baseText
if {!$anchorCheck} {append bText "(anchor missing) "}
if {!$caseOK} {append bText "(case doesn't match) "}
if {$homepage == ""} {
set line [string range $f $filebase end]
} else {
set line [string range $f [expr [string length $isInFolder] + 1] end]
}
set l [expr 20 - [string length [file tail $f]]]
set ln [expr 5 - [string length $linenum]]
set href [string trim [string range $filecont [lindex $href 0] [lindex $href 1]]]
append line "[format "%$l\s" ""] Line $linenum:[format "%$ln\s" ""]$bText$href"\
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t∞$f"
puts $fidr $line
set checkFail 1
}
} elseif {!$checking && [lsearch -exact $movedFiles $linkToPath] >=0 } {
set href [string trim [string range $filecont [lindex $href 0] [lindex $href 1]]]
puts $fidr [list $f $linenum $base $path $epath $linkToPath $href]
}
set filecont [string range $filecont [lindex $url 1] end]
}
if {![eof $fid]} {
incr linenum [regsub -all $newln [string range $filecont 0 [expr [string length $filecont] - 301]] {} dummy]
set filecont "[string range $filecont [expr [string length $filecont] - 300] end][read $fid 16384]"
set limit [expr [eof $fid] ? 0 : 300]
} else {
break
}
}
}
close $fid
}
close $fid0
catch {removeFile $files}
catch {unset htmlCaseFolders htmlCaseFiles filecont}
message ""
if {$checking == 1} {
if {$checkFail} {
seek $fidr 0
new -n "* Invalid URLs *" -g $tileLeft $tileTop $tileWidth $errorHeight
insertText "Incorrect links: (<uparrow> and <downarrow> to browse, <return> to go to file,\ropt-<return> to select a new file)\r[read $fidr]"
htmlSetWin Brws
} else {
alertnote "All links are OK."
}
close $fidr
catch {removeFile [lindex $result 1]}
} elseif {!$checking} {
return $result
} else {
return $toCheck
}
}
proc htmlCheckAnchor {anchorFile url} {
regexp {[^#]*#(.*)} $url dum anchor
if {[catch {open $anchorFile r} fid]} {return 1}
set exp "<!--|<(\[Aa\]|\[mM\]\[aA\]\[pP\])\[ \t\r\n\]+\[^>\]*\[nN\]\[aA\]\[mM\]\[eE\]=\"?$anchor\"?(>|\[ \t\r\n\]+\[^>\]*>)"
set filecont [read $fid 16384]
set limit [expr [eof $fid] ? 0 : 300]
set comment 0
while {1} {
while {$comment || ([regexp -indices $exp $filecont anch] &&
[expr [string length $filecont] - [lindex $anch 0]] > $limit)} {
if {$comment || [string range $filecont [lindex $anch 0] [lindex $anch 1]] == "<!--"} {
if {$comment} {
set anch {0 0}
set subcont $filecont
} else {
set subcont [string range $filecont [expr [lindex $anch 1] + 1] end]
}
if {[regexp -indices -- "-->" $subcont cend] &&
[expr [string length $subcont] - [lindex $cend 0]] > $limit} {
set filecont [string range $filecont [expr [lindex $anch 1] + [lindex $cend 1]] end]
set comment 0
continue
} else {
set comment 1
break
}
} else {
close $fid
return 1
}
}
if {![eof $fid]} {
set filecont "[string range $filecont [expr [string length $filecont] - 300] end][read $fid 16384]"
set limit [expr [eof $fid] ? 0 : 300]
} else {
break
}
}
close $fid
return 0
}
# Checks that the case in a link match the case in the path to file.
proc htmlCheckLinkCase {path link} {
global htmlCaseFolders htmlCaseFiles
set path [string trimright $path :]
set link [string trimright $link :]
if {[lsearch -exact $htmlCaseFiles $path] >= 0} {return 1}
set path [split $path :]
set plen [llength $path]
set llen [llength [split $link :]]
set j [expr $plen - $llen ? $plen - $llen - 1 : 0]
for {set i $j} {$i < $plen - 1} {incr i} {
set l [lindex $path [expr $i + 1]]
set psub [join [lrange $path 0 $i] :]
if {[lsearch -exact $htmlCaseFolders $psub] < 0} {
lappend htmlCaseFolders $psub
append htmlCaseFiles " " [glob -nocomplain "$psub:*"]
}
if {[lsearch -exact $htmlCaseFiles "$psub:$l"] < 0} {return 0}
}
return 1
}
#===============================================================================
# Moving files
#===============================================================================
# Moves files from one folder to another and update all links to the moved files
# as well as all links in the moved files.
proc htmlMoveFiles {} {
global HTMLmodeVars
# Check that a home page is defined.
if {![htmlIsThereAHomePage]} {return}
if {[htmlAllSaved "{All windows must be saved before you can moves files. Save?}"] == "no"} {return}
# Get folder to move from.
if {[catch {htmlGetDir "Move from."} fromFolder]} {return}
set base [htmlBASEfromPath $fromFolder]
# Is this folder in a home page folder?
if {[lindex $base 0] == "file:///"} {
alertnote "'[file tail $fromFolder]' is not in a home page folder or an include folder."
return
}
set fromPath [lindex $base 1]
set homepage [lindex $base 3]
set fromBase [lindex $base 0]
set isInInclFldr [lindex $base 4]
set inclFld [lindex $base 5]
# Check that the corresponding include or home page folder exists.
if {$isInInclFldr} {
if {![file isdirectory $homepage]} {
alertnote "Could not find the corresponding home page folder for\
${fromBase}$fromPath. Fix that and try again."
htmlHomePages "${fromBase}$fromPath"
return
}
} elseif {$inclFld != "" && ![file isdirectory $inclFld]} {
alertnote "Could not find the corresponding include folder for\
${fromBase}$fromPath. Fix that and try again."
htmlHomePages "${fromBase}$fromPath"
return
}
# Get files to move.
set files [glob -nocomplain "$fromFolder:*"]
foreach f $files {
if {![file isdirectory $f]} {
lappend filelist [file tail $f]
}
}
if {![info exists filelist]} {
alertnote "Empty folder."
return
}
if {[catch {listpick -p "Select files to move." -l $filelist} movefiles] || \
![string length $movefiles]} {return}
# Get folder to move to.
if {[catch {htmlGetDir "Move to."} toFolder]} {return}
if {$fromFolder == $toFolder} {
alertnote "This is the same folder as you moved from."
return
}
# Is this folder in the same home page folder?
if {!$isInInclFldr && ![string match "${homepage}:*" "$toFolder:"] ||
$isInInclFldr && ![string match "${inclFld}:*" "$toFolder:"]} {
set msg {"home page" "" "" "" "include"}
alertnote "'[file tail $toFolder]' is not in the same [lindex $msg $isInInclFldr] folder."
return
}
# Move the files.
foreach f $movefiles {
if {[file exists "$toFolder:$f"]} {
if {[askyesno "Replace '$f' in folder '[file tail $toFolder]'?"] == "yes"} {
removeFile "$toFolder:$f"
} else {
continue
}
}
set reo 0
foreach w [winNames -f] {
if {[stripNameCount $w] == "$fromFolder:$f"} {
alertnote "'[file tail $w]' must be closed before it can be moved. It will be reopened again."
bringToFront $w
killWindow
set reo 1
}
}
if {[catch {mv "$fromFolder:$f" "$toFolder:$f"}] && ![file exists "$toFolder:$f"]} {
alertnote "Could not move $f. An error occurred."
if {$reo} {lappend reOpen "$fromFolder:$f"}
} else {
lappend movedFiles "$fromFolder:$f"
lappend movedFiles2 "$toFolder:$f"
if {$reo} {lappend reOpen "$toFolder:$f"}
}
}
if {[info exists movedFiles] && $isInInclFldr} {
if {[lindex [dialog -w 400 -h 70 -t "Files have been moved. Update links?" \
10 10 290 30 -b Update 20 40 85 60 -b Cancel 105 40 170 60] 0]} {
set changed ""
set num [htmlUpdateAfterMove2 $movedFiles $movedFiles2 $fromBase $fromPath $inclFld]
set x [htmlUpdateAfterMove3 $movedFiles $movedFiles2 $homepage $inclFld]
incr num [lindex $x 0]
set changed [concat $changed [lindex $x 1]]
}
} elseif {[info exists movedFiles]} {
set box " -t {Files have been moved. Update links?} 10 10 390 30"
if {$inclFld != ""} {
append box " -r {Update both home page folder and include folder} 1 10 40 390 55 \
-r {Update only home page folder} 0 10 60 390 75 -r {Update only include folder} 0 10 80 390 95"
set he 140
} else {
set he 70
}
append box " -b Update 20 [expr $he - 30] 85 [expr $he - 10] -b Cancel 105 [expr $he - 30] 170 [expr $he - 10]"
set values [eval [concat dialog -w 400 -h $he $box]]
if {$inclFld != "" && ([lindex $values 0] || [lindex $values 1]) && [lindex $values 3] ||
$inclFld == "" && [lindex $values 0]} {
set x [htmlUpdateAfterMove $movedFiles $movedFiles2 $fromBase $fromPath $homepage $homepage]
set num [lindex $x 0]
set changed [lindex $x 1]
incr num [htmlUpdateAfterMove2 $movedFiles $movedFiles2 $fromBase $fromPath $homepage]
}
if {$inclFld != "" && ([lindex $values 0] || [lindex $values 2]) && [lindex $values 3]} {
set x [htmlUpdateAfterMove $movedFiles $movedFiles2 $fromBase $fromPath $homepage $inclFld]
incr num [lindex $x 0]
set changed [concat $changed [lindex $x 1]]
}
}
catch {message "$num files has been modified including the ones moved."}
if {[info exists reOpen] && [askyesno "Reopen previously closed windows?"] == "yes"} {
foreach r $reOpen {
edit $r
}
}
if {[llength $changed] && [askyesno "Update affected windows?"] == "yes"} {
foreach r $changed {
bringToFront $r
revert
}
}
}
# Updates links to moved files.
proc htmlUpdateAfterMove {movedFiles movedFiles2 fromBase fromPath homepage isinfld} {
global htmlURLAttr
set allfiles [htmlAllHTMLfiles $isinfld 1 $movedFiles2]
# Build regular expressions with URL attrs.
set exp "("
foreach attr $htmlURLAttr {
append exp "$attr|"
}
set exp [string trimright $exp |]
append exp ")"
set exprr "${exp}(\"\[^\">\]+\"|\[^ \\t\\n\\r>\]+)"
set exprr2 {(url)\((\"?[^\"\)]+\"?)\)}
# Update links to the moved files.
set toModify [htmlScanFiles $allfiles $fromBase $fromPath $homepage $isinfld 0 0 $movedFiles]
set fidr [lindex $toModify 0]
seek $fidr 0
set num 0
set changed ""
set thisfile ""
while {![eof $fidr]} {
gets $fidr modify
if {$modify == ""} {continue}
set fil [lindex $modify 0]
if {$thisfile != $fil} {
if {[string length $thisfile]} {
if {[catch {open $thisfile w} fid]} {
alertnote "Could not update [file tail $thisfile]. An error occurred."
} else {
puts -nonewline $fid [join $filecont "\r"]
close $fid
}
}
message "Modifying [file tail $fil]…"
foreach w [winNames -f] {
if {[stripNameCount $w] == "$fil"} {
lappend changed $w
}
}
set fid [open $fil r]
incr num
set filec [read $fid]
close $fid
if {[regexp {\n} $filec]} {
set newln "\n"
} else {
set newln "\r"
}
set filec [split $filec $newln]
set filecont ""
foreach fc $filec {
lappend filecont [string trimleft $fc "\r"]
}
}
set thisfile $fil
set linenum [expr [lindex $modify 1] - 1]
set line [lindex $filecont $linenum]
set path [lindex $movedFiles2 [lsearch -exact $movedFiles [lindex $modify 5]]]
set lnk [htmlBASEfromPath $path]
if {[lindex $modify 2] == [lindex $lnk 0]} {
set linkTo [htmlRelativePath "[lindex $modify 3][lindex $modify 4]" "[lindex $lnk 1][lindex $lnk 2]"]
} else {
set linkTo [join [lrange $lnk 0 2] ""]
}
set linkTo [htmlURLescape2 $linkTo]
regsub -all {[\(\)]} [lindex $modify 6] {\\\0} tomod
regexp -indices $tomod $line href
if {![regexp -nocase -indices $exprr [string range $line [lindex $href 0] [lindex $href 1]] a b url]} {
regexp -nocase -indices $exprr2 [string range $line [lindex $href 0] [lindex $href 1]] a b url
}
set anchor ""
regexp {[^#]*(#[^\"]*)} $tomod a anchor
set line "[string range $line 0 [expr [lindex $href 0] + [lindex $url 0] - 1]]\"$linkTo$anchor\"[string range $line [expr [lindex $href 0] + [lindex $url 1] + 1] end]"
set filecont [lreplace $filecont $linenum $linenum $line]
}
if {$thisfile != ""} {
if {[catch {open $thisfile w} fid]} {
alertnote "Could not update [file tail $thisfile]. An error occurred."
} else {
puts -nonewline $fid [join $filecont "\r"]
close $fid
}
}
close $fidr
catch {removeFile [lindex $toModify 1]}
return [list $num $changed]
}
# Updates links in moved files.
proc htmlUpdateAfterMove2 {movedFiles movedFiles2 fromBase fromPath homepage} {
global htmlURLAttr
set expBase "<(base\[ \\t\\n\\r\]+)\[^>\]*>"
set expBase2 "(href=)\"?(\[^ \\t\\n\\r\">\]+)\"?"
# Build regular expressions with URL attrs.
set exp "("
foreach attr $htmlURLAttr {
append exp "$attr|"
}
set exp [string trimright $exp |]
append exp ")"
set exprr1 "<!--|\[ \\t\\n\\r\]+$exp\"?(\[^ \\t\\n\\r\">\]+)\"?"
set exprr2 {/\*|[ \t\n\r]+(url)\(\"?([^\"\)]+)\"?\)}
set commStart1 "<!--"
set commEnd1 "-->"
set commStart2 {/*}
set commEnd2 {\*/}
set num 0
foreach f $movedFiles2 {
getFileInfo $f finfo
if {$finfo(type) != "TEXT"} {continue}
message "Modifying [file tail $f]…"
set created $finfo(created)
set fid [open $f r]
set filecont [read $fid 16384]
set limit [expr [eof $fid] ? 0 : 300]
set temp [htmlOpenAfile]
set tempf [lindex $temp 1]
set tempfid [lindex $temp 0]
set oldfile [lindex $movedFiles [lsearch -exact $movedFiles2 $f]]
set base $fromBase
set path $fromPath
set hpPath $homepage
set epath [string range $oldfile [expr [string length $homepage] + 1] end]
regsub -all {:} $epath {/} epath
# Replace newline chars in IBM files.
regsub -all "\n\r" $filecont "\r" filecont
# If BASE is used, only modify links to moved files.
set hasBase 0
if {[regexp -nocase -indices $expBase $filecont this]} {
set preBase [string range $filecont 0 [lindex $this 0]]
set comm 0
while {[regexp -indices {<!--} $preBase bCom]} {
set preBase [string range $preBase [expr [lindex $bCom 1] - 1] end]
set comm 1
if {[regexp -indices -- {-->} $preBase bCom]} {
set preBase [string range $preBase [expr [lindex $bCom 1] - 1] end]
set comm 0
} else {
break
}
}
if {!$comm && [regexp -nocase $expBase2 [string range $filecont [lindex $this 0] [lindex $this 1]] d1 d2 url1]} {
set hasBase 1
}
}
if {$hasBase && ![catch {htmlBASEpieces $url1} basestr]} {
set base [lindex $basestr 0]
set path [lindex $basestr 1]
set epath [lindex $basestr 2]
set hpPath ""
}
incr num
for {set i1 1} {$i1 < 3} {incr i1} {
if {$i1 == 2} {
close $fid
seek $tempfid 0
set fid $tempfid
set filecont [read $fid 16384]
set limit [expr [eof $fid] ? 0 : 300]
set temp [htmlOpenAfile]
set tempfid [lindex $temp 0]
}
set commStart [set commStart$i1]
set commEnd [set commEnd$i1]
set exprr [set exprr$i1]
set comment 0
while {1} {
while {$comment || ([regexp -nocase -indices $exprr $filecont href b url] &&
[expr [string length $filecont] - [lindex $href 0]] > $limit)} {
# Comment?
if {$comment || [string range $filecont [lindex $href 0] [lindex $href 1]] == $commStart} {
if {$comment} {
set href {0 0}
set subcont $filecont
} else {
set subcont [string range $filecont [expr [lindex $href 1] + 1] end]
}
if {[regexp -indices -- $commEnd $subcont cend] &&
[expr [string length $subcont] - [lindex $cend 0]] > $limit} {
puts -nonewline $tempfid [string range $filecont 0 [expr [lindex $href 1] + [lindex $cend 1] - 1]]
set filecont [string range $filecont [expr [lindex $href 1] + [lindex $cend 1]] end]
set comment 0
continue
} else {
set comment 1
break
}
}
set urltxt [string range $filecont [lindex $url 0] [lindex $url 1]]
# No need to update links beginning with a /
if {[string index $urltxt 0] == "/"} {
puts -nonewline $tempfid [string range $filecont 0 [lindex $url 1]]
set filecont [string range $filecont [expr [lindex $url 1] + 1] end]
continue
}
set anchor ""
regexp {[^#]*(#[^\"]*)} $urltxt a anchor
set urltxt [htmlURLunEscape $urltxt]
if {[catch {lindex [htmlPathToFile $base $path $epath $hpPath $urltxt] 0} topath]} {set topath ""}
# Ignore anchors if not moved and BASE.
# Is the link pointing to a previously moved file?
if {[set mvind [lsearch -exact $movedFiles $topath]] >= 0} {
set topath [lindex $movedFiles2 $mvind]
if {!$hasBase && [string index $urltxt 0] == "#"} {set topath ""}
} elseif {[string index $urltxt 0] == "#"} {
set topath ""
}
if {$hasBase && [regexp -nocase -indices $expBase $filecont thisLine] \
&& [regexp -nocase $expBase2 [string range $filecont [lindex $thisLine 0] [lindex $thisLine 1]]]\
&& [lindex $thisLine 0] < [lindex $url 0] && [lindex $thisLine 1] > [lindex $url 1]} {
set topath ""
}
if {[string length $topath]} {
set lnk [htmlBASEfromPath $topath]
if {!$hasBase} {
set lnk1 [htmlBASEfromPath $f]
set path2 [lindex $lnk1 1]
set epath2 [lindex $lnk1 2]
} else {
set path2 $path
set epath2 $epath
}
if {$base == [lindex $lnk 0]} {
set newurl [htmlRelativePath "$path2$epath2" "[lindex $lnk 1][lindex $lnk 2]"]
} else {
set newurl [join [lrange $lnk 0 2] ""]
}
append newurl $anchor
} elseif {!$hasBase && ($urltxt == ".." || [string range $urltxt 0 2] == "../")} {
# Special case with relative links outside home page.
set urlspl [split $urltxt /]
set old [split $oldfile :]
set new [split $f :]
if {[llength $new] > [llength $old]} {
set newurl ""
for {set i 0} {$i < [expr [llength $new] - [llength $old]]} {incr i} {
append newurl "../"
}
append newurl $urltxt
} else {
set ok 1
for {set i 0} {$i < [expr [llength $old] - [llength $new]]} {incr i} {
if {[lindex $urlspl $i] != ".."} {set ok 0}
}
if {$ok} {
set newurl "[join [lrange $urlspl [expr [llength $old] - [llength $new]] end] /]$anchor"
} else {
set newurl $urltxt
}
}
} else {
set newurl $urltxt
}
puts -nonewline $tempfid [string range $filecont 0 [expr [lindex $url 0] - 1]]
puts -nonewline $tempfid [htmlURLescape2 $newurl]
set filecont [string range $filecont [expr [lindex $url 1] + 1] end]
}
if {![eof $fid]} {
puts -nonewline $tempfid [string range $filecont 0 [expr [string length $filecont] - 301]]
set filecont "[string range $filecont [expr [string length $filecont] - 300] end][read $fid 16384]"
set limit [expr [eof $fid] ? 0 : 300]
} else {
break
}
}
puts -nonewline $tempfid $filecont
}
close $fid
close $tempfid
if {[catch {removeFile $f}] && [file exists $f]} {
alertnote "Could not update [file tail $f]. An error occurred."
} else {
catch {copyFile [lindex $temp 1] $f; setFileInfo $f created $created}
}
catch {removeFile [lindex $temp 1]}
catch {removeFile $tempf}
}
return $num
}
# Updates include links to moved files in include folder.
proc htmlUpdateAfterMove3 {movedFiles movedFiles2 homepage inclFldr} {
set num 0
set changed ""
set allFiles [htmlAllHTMLfiles $homepage]
set fid0 [open $allFiles]
while {![eof $fid0]} {
gets $fid0 fil
if {$fil == "" || [catch {open $fil} fid]} {continue}
set filecont [read $fid 16384]
set limit [expr [eof $fid] ? 0 : 300]
message "Looking at [file tail $fil]…"
getFileInfo $fil finfo
set created $finfo(created)
regsub -all "\n\r" $filecont "\r" filecont
set temp [htmlOpenAfile]
set tmpfid [lindex $temp 0]
set ismod 0
while {1} {
while {[regexp -nocase -indices {<!--[ \t\r\n]+#INCLUDE[ \t\r\n]+[^>]+>} $filecont res] &&
[expr [string length $filecont] - [lindex $res 0]] > $limit} {
set link [string range $filecont [lindex $res 0] [lindex $res 1]]
if {[regexp -nocase -indices {FILE=\"([^\"]+)\"} $link dum res1] &&
[set ind [lsearch -exact $movedFiles [htmlResolveInclPath [htmlUnQuote \
[string range $link [lindex $res1 0] [lindex $res1 1]]] $inclFldr:]]] >= 0} {
puts -nonewline $tmpfid [string range $filecont 0 [expr [lindex $res 0] + [lindex $res1 0] - 1]]
puts -nonewline $tmpfid [htmlQuote [htmlConvertInclPath [lindex $movedFiles2 $ind] $inclFldr:]]
puts -nonewline $tmpfid [string range $filecont [expr [lindex $res 0] + [lindex $res1 1] + 1] [lindex $res 1]]
set ismod 1
message "Modifying [file tail $fil]…"
} else {
puts -nonewline $tmpfid [string range $filecont 0 [lindex $res 1]]
}
set filecont [string range $filecont [expr [lindex $res 1] + 1] end]
}
if {![eof $fid]} {
puts -nonewline $tmpfid [string range $filecont 0 [expr [string length $filecont] - 301]]
set filecont "[string range $filecont [expr [string length $filecont] - 300] end][read $fid 16384]"
set limit [expr [eof $fid] ? 0 : 300]
} else {
break
}
}
puts -nonewline $tmpfid $filecont
close $tmpfid
close $fid
if {$ismod} {
if {[catch {removeFile $fil}] && [file exists $fil]} {
alertnote "Could not update [file tail $fil]. An error occurred."
} else {
catch {copyFile [lindex $temp 1] $fil; setFileInfo $fil created $created}
}
incr num
foreach w [winNames -f] {
if {[stripNameCount $w] == "$fil"} {
lappend changed $w
}
}
}
catch {removeFile [lindex $temp 1]}
}
close $fid0
catch {removeFile $allFiles}
return [list $num $changed]
}
#===============================================================================
# Includes
#===============================================================================
proc htmlConvertInclPath {fil path} {
if {$path != "" && [string match "${path}*" $fil]} {
return ":INCLUDE:[string range $fil [string length $path] end]"
}
return $fil
}
# Inserts new include tags at the current position.
proc htmlInsertIncludeTags {} {
set sexpr {<!--[ \t\r\n]+#INCLUDE[ \t\r\n]+[^>]+>}
set eexpr {<!--[ \t\r\n]+/#INCLUDE[ \t\r\n]+[^>]+>}
if {![catch {search -s -f 0 -r 1 -i 1 -m 0 $sexpr [getPos]} res] &&
([catch {search -s -f 0 -r 1 -i 1 -m 0 $eexpr [getPos]} res1]
|| [lindex $res 0] > [lindex $res1 0])} {
alertnote "Current position is inside an include container."
return
}
if {![catch {search -s -f 1 -r 1 -i 1 -m 0 $eexpr [getPos]} res] &&
([catch {search -s -f 1 -r 1 -i 1 -m 0 $sexpr [getPos]} res1]
|| [lindex $res 0] < [lindex $res1 0])} {
alertnote "Current position is inside an include container."
return
}
if {[catch {getfile "Select file to include."} fil]} {return}
if {![htmlIsTextFile $fil alertnote]} {return}
set fil1 [htmlQuote [htmlConvertInclPath $fil \
[htmlWhichInclFolder [stripNameCount [lindex [winNames -f] 0]]]]]
set text "<!-- [htmlSetCase {#INCLUDE FILE=}]\"$fil1\" -->\r\r"
if {![catch {readFile $fil} intext]} {
regsub -all "\n\r" $intext "\r" intext
# Remove include tags from inserted text
regsub -all -nocase $sexpr $intext "" intext
regsub -all -nocase $eexpr $intext "" intext
append text $intext
}
append text "\r\r" "<!-- [htmlSetCase /#INCLUDE] -->"
insertText [htmlOpenCR "" 1] $text "\r\r"
}
# Updates the text between all include tags.
proc htmlUpdateWindow {} {htmlUpdateInclude Window}
proc htmlUpdateHomePage {} {htmlUpdateInclude Home}
proc htmlUpdateFolder {} {htmlUpdateInclude Folder}
proc htmlUpdateFile {} {htmlUpdateInclude File}
proc htmlUpdateInclude {where} {
global HTMLmodeVars winModes
global tileLeft tileTop tileWidth errorHeight
set sexpr {<!--[ \t\r\n]+#INCLUDE[ \t\r\n]+[^>]+>}
set eexpr {<!--[ \t\r\n]+/#INCLUDE[ \t\r\n]+[^>]+>}
if {$where == "Window"} {
set wname [stripNameCount [lindex [winNames -f] 0]]
set inclFldr [htmlWhichInclFolder $wname]
set pos 0
while {![catch {search -s -f 1 -r 1 -i 1 -m 0 $sexpr $pos} res]} {
set lnum [lindex [posToRowCol [lindex $res 0]] 0]
set ln [expr 5 - [string length $lnum]]
if {[catch {search -s -f 1 -r 1 -i 1 -m 0 $eexpr [lindex $res 1]} res1]} {
append err "Line $lnum:[format "%$ln\s" ""]Opening include tag without a matching end tag."\
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t∞$wname\r"
break
}
if {![catch {search -s -f 1 -r 1 -i 1 -m 0 $sexpr [lindex $res 1]} res2]
&& [lindex $res2 0] < [lindex $res1 0]} {
append err "Line $lnum:[format "%$ln\s" ""]Nested include tags."\
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t∞$wname\r"
set pos [lindex $res1 1]
continue
}
if {[catch {htmlReadInclude [eval getText $res] 1 $inclFldr} text]} {
append err "Line $lnum:[format "%$ln\s" ""]$text"\
"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t∞$wname\r"
set pos [lindex $res1 1]
} else {
replaceText [lindex $res 1] [lindex $res1 0] "\r\r" $text "\r\r"
set pos [expr [lindex $res 1] + [string length $text] + 4]
}
}
} else {
if {[htmlAllSaved "-c {Save all open windows before updating?}"] == "cancel"} {return}
if {$where == "File"} {
if {[catch {getfile "Select file to update."} files]} {return}
if {![htmlIsTextFile $files alertnote]} {return}
set inclFldr [htmlWhichInclFolder $files]
set folder [file dirname $files]
set filelist [htmlOpenAfile]
puts [lindex $filelist 0] $files
close [lindex $filelist 0]
set files [lindex $filelist 1]
} elseif {$where == "Folder"} {
if {[catch {htmlGetDir "Update folder:"} folder]} {return}
set inclFldr [htmlWhichInclFolder "${folder}:"]
set subFolders [expr ![string compare yes [askyesno "Update files in subfolders?"]]]
if {$subFolders} {
set files [htmlAllHTMLfiles $folder]
} else {
set files [htmlGetHTMLfiles $folder]
}
} else {
if {![htmlIsThereAHomePage] ||
[catch {htmlWhichHomePage "update"} hp]} {return}
set folder [lindex $hp 0]
set inclFldr [htmlWhichInclFolder "${folder}:"]
set files [htmlAllHTMLfiles $folder]
}
set fid0 [open $files]
while {![eof $fid0]} {
gets $fid0 f
if {$f == "" || [catch {open $f} fid]} {continue}
message "Updating [file tail $f]…"
getFileInfo $f finfo
set created $finfo(created)
set filecont [read $fid 16384]
set limit [expr [eof $fid] ? 0 : 300]
regsub -all "\n\r" $filecont "\r" filecont
if {[regexp {\n} $filecont]} {
set newln "\n"
} else {
set newln "\r"
}
set linenum 1
set ismod 0
set errf [string range $f [expr [string length $folder] + 1] end]
set temp [htmlOpenAfile]
set tmpfid [lindex $temp 0]
set opening 0
while {1} {
while {$opening || ([regexp -nocase -indices $sexpr $filecont res] &&
[expr [string length $filecont] - [lindex $res 0]] > $limit)} {
if {!$opening} {
incr linenum [regsub -all $newln [string range $filecont 0 [lindex $res 0]] {} dummy]
set l [expr 20 - [string length [file tail $f]]]
set ln [expr 5 - [string length $linenum]]
puts -nonewline $tmpfid [string range $filecont 0 [lindex $res 1]]
set readName [string range $filecont [lindex $res 0] [lindex $res 1]]
set filecont [string range $filecont [expr [lindex $res 1] + 1] end]
}
if {![regexp -nocase -indices $eexpr $filecont res1] ||
[expr [string length $filecont] - [lindex $res1 0]] <= $limit} {
if {[eof $fid]} {
append err [htmlBrwsErr $errf $l $linenum $ln "Opening include tag without a matching end tag." $f]
} else {
set opening 1
}
break
}
set toReplace [string trim [string range $filecont 0 [expr [lindex $res1 0] - 1]]]
set opening 0
if {[regexp -nocase -indices $sexpr $filecont res2]
&& [lindex $res2 0] < [lindex $res1 0]} {
append err [htmlBrwsErr $errf $l $linenum $ln "Nested include tags." $f]
puts -nonewline $tmpfid [string range $filecont 0 [lindex $res1 1]]
incr linenum [regsub -all $newln [string range $filecont 0 [lindex $res1 1]] {} dummy]
set filecont [string range $filecont [expr [lindex $res1 1] + 1] end]
continue
}
if {[catch {htmlReadInclude $readName 0 $inclFldr} text]} {
append err [htmlBrwsErr $errf $l $linenum $ln $text $f]
puts -nonewline $tmpfid [string range $filecont 0 [lindex $res1 1]]
incr linenum [regsub -all $newln [string range $filecont 0 [lindex $res1 1]] {} dummy]
set filecont [string range $filecont [expr [lindex $res1 1] + 1] end]
continue
}
lappend modified $f
if {[string trim $text] != $toReplace} {
set ismod 1
}
puts -nonewline $tmpfid "$newln$newln$text$newln$newln"
puts -nonewline $tmpfid [string range $filecont [lindex $res1 0] [lindex $res1 1]]
incr linenum [regsub -all $newln [string range $filecont 0 [lindex $res1 1]] {} dummy]
set filecont [string range $filecont [expr [lindex $res1 1] + 1] end]
}
if {![eof $fid]} {
if {$opening} {
append filecont [read $fid 16384]
} else {
puts -nonewline $tmpfid [string range $filecont 0 [expr [string length $filecont] - 301]]
incr linenum [regsub -all $newln [string range $filecont 0 [expr [string length $filecont] - 301]] {} dummy]
set filecont "[string range $filecont [expr [string length $filecont] - 300] end][read $fid 16384]"
}
set limit [expr [eof $fid] ? 0 : 300]
} else {
break
}
}
close $fid
if {$ismod} {puts -nonewline $tmpfid $filecont}
close $tmpfid
if {$ismod} {
set linenum 1
set opening 0
set done 0
set fid [open [set temp1 [lindex $temp 1]]]
set filecont [read $fid 16384]
set limit [expr [eof $fid] ? 0 : 300]
set temp [htmlOpenAfile]
set tmpfid [lindex $temp 0]
while {1} {
if {$opening || ([regexp -nocase -indices {<!--[ \t\r\n]+#LASTMODIFIED[ \t\r\n]+[^>]+>} $filecont res] &&
[expr [string length $filecont] - [lindex $res 0]] > $limit)} {
if {!$opening} {
incr linenum [regsub -all "\n" [string range $filecont 0 [lindex $res 0]] {} dummy]
set l [expr 20 - [string length [file tail $f]]]
set ln [expr 5 - [string length $linenum]]
puts -nonewline $tmpfid [string range $filecont 0 [lindex $res 1]]
set lastMod [string range $filecont [lindex $res 0] [lindex $res 1]]
set filecont [string range $filecont [expr [lindex $res 1] + 1] end]
}
if {![regexp -nocase -indices {<!--[ \t\r\n]+/#LASTMODIFIED[ \t\r\n]+[^>]+>} $filecont res1] ||
[expr [string length $filecont] - [lindex $res1 0]] <= $limit} {
if {[eof $fid]} {
append err [htmlBrwsErr $errf $l $linenum $ln "Opening 'last modified' tag without a matching closing tag." $f]
} else {
set opening 1
}
} else {
set str [htmlGetLastMod $lastMod]
set done 1
if {$str == "0"} {
append err [htmlBrwsErr $errf $l $linenum $ln "Invalid 'last modified' tags." $f]
} else {
puts -nonewline $tmpfid "\r$str\r[string range $filecont [lindex $res1 0] end]"
set filecont ""
}
}
}
if {![eof $fid] && !$done} {
if {$opening} {
append filecont [read $fid 16384]
} else {
puts -nonewline $tmpfid [string range $filecont 0 [expr [string length $filecont] - 301]]
incr linenum [regsub -all "\n" [string range $filecont 0 [expr [string length $filecont] - 301]] {} dummy]
set filecont "[string range $filecont [expr [string length $filecont] - 300] end][read $fid 16384]"
}
set limit [expr [eof $fid] ? 0 : 300]
} else {
break
}
}
puts -nonewline $tmpfid $filecont
while {![eof $fid]} {
puts -nonewline $tmpfid [read $fid 16384]
}
close $fid
close $tmpfid
if {[catch {removeFile $f}] && [file exists $f]} {
append err "$errf[format "%$l\s" ""]; Could not write update to file. An error occurred.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t∞$f\r"
} else {
catch {copyFile [lindex $temp 1] $f; setFileInfo $f created $created}
}
catch {removeFile $temp1}
}
catch {removeFile [lindex $temp 1]}
}
close $fid0
catch {removeFile $files}
}
if {[info exists err]} {
new -n "* Errors *" -g $tileLeft $tileTop $tileWidth $errorHeight
set name [lindex [winNames] 0]
insertText "Errors: (<uparrow> and <downarrow> to browse, <return> to go to file)\r\r"
insertText $err
htmlSetWin Brws
} else {
message "$where updated successfully."
}
if {[info exists modified]} {
foreach w [winNames -f] {
if {[lsearch -exact $modified [stripNameCount $w]] >= 0} {
if {[askyesno "Update affected windows?"] == "yes"} {
foreach ww [winNames -f] {
if {[lsearch -exact $modified [stripNameCount $ww]] >= 0} {
bringToFront $ww
revert
}
}
}
if {[info exists err]} {bringToFront $name}
return
}
}
}
}
# Read content of a file to be included.
proc htmlReadInclude {incl nr fldr} {
if {![regexp -nocase {file=\"([^\"]+)\"} $incl dum fil]} {
error "Invalid opening include tag."
}
if {$fldr == "" && [regexp -nocase {^:INCLUDE:} $fil]} {error ":INCLUDE: doesn't map to a folder."}
set fil [htmlResolveInclPath [htmlUnQuote $fil] $fldr]
if {![file exists $fil]} {
error "File not found."
}
if {[catch {readFile $fil} text]} {
error "Could not read file."
}
regsub -all "\n\r" $text "\r" text
if {$nr} {regsub -all "\n" $text "\r" text}
# Remove include tags from inserted text
regsub -all -nocase "<!--\[ \t\r\n\]+/?#INCLUDE\[ \t\r\n\]+\[^>\]+>" $text "" text
return $text
}